#include "chargen.h"
#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>
#include <boost/bind.hpp>
#include <stdio.h>

using namespace muduo;
using namespace muduo::net;

ChargenServer::ChargenServer(EventLoop *loop, const InetAddress &listenAddr, bool print) 
	: server_(loop, listenAddr, "ChargenServer"),
	  transfered_(0),
	  startTime_(Timestamp::now()) {
	server_.setConnectionCallback(boost::bind(&ChargenServer::OnConnection, this, _1));
	server_.setMessageCallback(boost::bind(&ChargenServer::OnMessage, this, _1, _2, _3));
	server_.setWriteCompleteCallback(boost::bind(&ChargenServer::OnWriteComplete, this, _1));

	if (print)
		loop->runEvery(3.0, boost::bind(&ChargenServer::PrintThroughput, this));

	string line;
	for (int i = 33; i < 127; ++i)
		line.push_back(char(i));
	line += line;
	for (size_t i = 0; i < 127 - 33; ++i)
		message_ += line.substr(i, 72) + '\n';
}

void 
ChargenServer::Start() {
	server_.start();
}

void
ChargenServer::OnConnection(const TcpConnectionPtr &conn) {
	LOG_INFO << "ChargenServer - " << conn->peerAddress().toIpPort() << " -> "
	         << conn->localAddress().toIpPort() << " is "
	         << (conn->connected() ? "UP" : "DOWN");
	if (conn->connected()) {
		conn->setTcpNoDelay(true);
		conn->send(message_);
	}
}

void
ChargenServer::OnMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp time) {
	string msg(buf->retrieveAllAsString());
	LOG_INFO << conn->name() << " discards " << msg.size()
	         << " bytes received at " << time.toString();
}

void
ChargenServer::OnWriteComplete(const TcpConnectionPtr &conn) {
	transfered_ += message_.size();
	conn->send(message_); // 发送完了才发送下一条消息，防止客户端接收缓慢的情况。
}

void
ChargenServer::PrintThroughput() {
	Timestamp endTime =  Timestamp::now();
	double time = timeDifference(endTime, startTime_);
	printf("%4.3f MiB/s\n", static_cast<double>(transfered_) / time / 1024 / 1024);
	transfered_ = 0;
	startTime_ = endTime;
}
